1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
@Slf4j @Component @SuppressWarnings({"deprecation"}) public class RepeatSubmitInterceptorHandler implements HandlerInterceptor {
@Resource private ObjectMapper jacksonObjectMapper;
@Autowired RedisUtils redisUtils;
public static final String REPEAT_RLOCK = "RLock"; public static final String LOCK_SIGN = "LOCK_SIGN";
private static final Integer LOCK_TIME = 30;
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (request.getContentType() != null && request.getContentType().toUpperCase().contains(MediaType.APPLICATION_JSON_VALUE.toUpperCase()) && HttpMethod.POST.matches(request.getMethod())) { if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); RepeatSubmit repeatSubmit = method.getAnnotation(RepeatSubmit.class); if (Objects.nonNull(repeatSubmit) && this.isRepeatSubmit(request)) { JsonResult result = JsonResult.error("不允许重复提交,请稍后再试"); renderResponse(response, result); return false; } } } return true; }
public boolean isRepeatSubmit(HttpServletRequest servletRequest) throws IOException { RepeatSubmitRequestWrapper request = new RepeatSubmitRequestWrapper(servletRequest); String requestURI = request.getRequestURI(); String token = request.getHeader("token"); String nowParams = ""; if (request.getContentType() != null && request.getContentType().toUpperCase().contains(MediaType.APPLICATION_JSON_VALUE.toUpperCase()) && HttpMethod.POST.matches(request.getMethod())) {
nowParams = DigestUtils.md5Hex(request.getBody()); } Map<String, String[]> parameterMap = request.getParameterMap(); if (parameterMap != null && !parameterMap.isEmpty()) { nowParams += DigestUtils.md5Hex(JSON.toJSONString(parameterMap)); }
String value = String.format("%s_%s_%s", token, requestURI, nowParams); String lockKey = RedisKeysEnum.getRedisKey(RedisKeysEnum.CACHE_REPEAT_KEY, DigestUtils.md5Hex(value)); String lockSign = UUID.randomUUID().toString(); Boolean val = redisUtils.setIfAbsent(lockKey, lockSign, LOCK_TIME, TimeUnit.SECONDS); request.setAttribute(REPEAT_RLOCK, lockKey); request.setAttribute(LOCK_SIGN, lockSign);
if (val == null) { return false; } else { return !val; } }
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { Object lockKey = request.getAttribute(REPEAT_RLOCK); Object lockSign = request.getAttribute(LOCK_SIGN); if (Objects.nonNull(lockKey)) { Object val = redisUtils.get(lockKey.toString()); if (val == null || val.toString().isEmpty()) { return; } if (Objects.equals(val.toString(), lockSign.toString())) { redisUtils.del(lockKey.toString()); } }
}
private boolean isMultipartFormDataPost(HttpServletRequest request) { String contentType = request.getContentType(); return (contentType != null && contentType.contains(MediaType.MULTIPART_FORM_DATA_VALUE) && HttpMethod.POST.matches(request.getMethod())); }
private void renderResponse(HttpServletResponse response, JsonResult result) throws IOException { response.setStatus(HttpStatus.OK.value()); response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setCharacterEncoding(StandardCharsets.UTF_8.name()); try (PrintWriter writer = response.getWriter()) { writer.print(jacksonObjectMapper.writeValueAsString(result)); } }
private byte[] mergeBytes(List<byte[]> values) { int lengthByte = 0; for (byte[] value : values) { lengthByte += value.length; } byte[] allBytes = new byte[lengthByte]; int countLength = 0; for (byte[] b : values) { System.arraycopy(b, 0, allBytes, countLength, b.length); countLength += b.length; } return allBytes; } }
|